<?php
namespace Tbf\Bundle\TbfBundle\Command;
use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Input\InputArgument;
use Tbf\Bundle\TbfBundle\Exception\BusinessException;

/**
 * 将数据库里面所有表的都修改为某一个引擎
 */
class DatabaseChangeEngineCommand extends TbfCommand
{
    protected function configure()
    {
        $this
            ->setName('tbf:database:change_engine')
            ->setDescription('convert all table engine')
            ->addArgument('engine', InputArgument::REQUIRED, 'the mysql engine set to be[innodb,memory,mysiam]')
            ->addOption('dump-sql',null,InputOption::VALUE_NONE,'view the sql going to run!')
            ->addOption('force',null,InputOption::VALUE_NONE,'update database schema');
    }

    protected function execute(InputInterface $input, OutputInterface $output)
    {
        $engine = $input->getArgument('engine');
        $engine = strtolower($engine);
        if (!in_array($engine, array('innodb', 'memory', 'mysiam'))) {
            throw new BusinessException('invaild engine type:' . $engine);
        }
        if ($input->getOption('dump-sql')) {
            foreach ($this->getAllSql($engine) as $sql) {
                $output->writeln($sql.';');
            }

            return;
        } elseif ($input->getOption('force')) {
            $this->getDbalConnection()->beginTransaction();
            foreach ($this->getAllSql($engine) as $sql) {
                $this->getDbalConnection()->query($sql);
            }
            $this->getDbalConnection()->commit();
        } else {
            throw new BusinessException('wrong command!!!');
        }
    }


    public function getAllSql($engine)
    {
        $sql = array();
        foreach ($this->getDbalConnection()->getSchemaManager()->listTableNames() as $table_name) {
            list($perpare_sql,$after_sql) = $this->getAlterTableEngineSql($table_name,$engine);
            $sql = array_merge($perpare_sql,$sql,$after_sql);
        }

        return $sql;
    }
    public function getAlterTableEngineSql($table_name, $engine)
    {
        if ($engine !== 'memory') {
            return array(array(),array('alter table ' . $table_name . ' ENGINE=' . $engine));
        }
        $table = $this->getDbalConnection()->getSchemaManager()->listTableDetails($table_name);
        $perpare_sql = array();
        $after_sql = array();
        foreach ($table->getColumns() as $column) {
            $type = $column->getType()->getName();
            if (in_array($type,array('text','blob'))) {
                $perpare_sql[] = 'alter table ' .$table_name.' CHANGE `'.$column->getName().'` `'.$column->getName().'` VARBINARY(10000) NOT NULL';
            }
        }
        foreach ($table->getForeignKeys() as $fk) {
            $perpare_sql[] = 'alter table '.$table_name.' drop foreign key '.$fk->getName();
        }
        $after_sql[] = 'alter table ' . $table_name . ' ENGINE=memory';

        return array($perpare_sql,$after_sql);
    }
}
